/**
*  Copyright (c) 2011, Alex Theodoridis
*  All rights reserved.

*  Redistribution and use in source and binary forms, with 
*  or without modification, are permitted provided that the 
*  following conditions are met:
*  Redistributions of source code must retain the above 
*  copyright notice, this list of conditions and the following disclaimer.
*  Redistributions in binary form must reproduce the above 
*  copyright notice, this list of conditions and the following
*  disclaimer in the documentation and/or other materials 
*  provided with the distribution.

*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
*  AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
*  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
*  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
*  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
*  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
*  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE,
*  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*/

#ifndef BEPNeuronH
#define BEPNeuronH
#include <NeuralNetwork/Neuron/Neuron.h>

namespace nn {

    namespace bp {

        /*
        * Represent the back error propagation Neuron trainer.
        * This class holds a pointer to neuron which should
        * be trained with back error propagation algorithm.
        */
        template<class Var>
        class BPNeuron {
        private:
            /**
            * Neuron for training.
            */
            typename utils::SharedPtr<Neuron<Var> > _neuron;

            /**
            * Neurons error delta
            */
            Var _delta;

            /**
            * The calculated differential of
            * neurons equation.
            */
            Var _differential;

        public:

            /**
            * Initialization constructor
            * @param neuron the pointer to
            * neuron which need to be trained
            */
            BPNeuron(const typename utils::SharedPtr<Neuron<Var> >& neuron) {
                if (neuron == NULL) {
                    throw NNException("Wrong neuron pointer", __FILE__, __LINE__);
                }

                _neuron = neuron;
            }

            /**
            * Will return the pointer to
            * trained neuron.
            * @returns the pointer to trained neuron.
            */
            const typename utils::SharedPtr<Neuron<Var> >& getNeuron(void) const {
                return _neuron;
            }

            /**
            * Will return the errors delta for
            * training neuron.
            * @returns the error deltas value.
            */
            const Var& getDelta(void) const {
                return _delta;
            }

            void setDelta(const Var& delta) {
                _delta = delta;
            }

			/*!
			* 
			*/
            const Var& calculateDifferential(void){
                const Var& output = _neuron->getOutput();
                typename utils::SharedPtr<IEquation<Var> > equation = _neuron->getEquation();
                if (equation != NULL) {
                    _differential = equation->calculateDifferential(output);
                    return _differential;
                }

                throw NNException("Wrong neuron equation found", __FILE__, __LINE__);
            }

            /**
            * Destructor.
            */
            virtual ~BPNeuron() throw () {}
        };

    }

}
//---------------------------------------------------------------------------
#endif
